package com.cjy.service.Impl;

import cn.hutool.core.util.ObjectUtil;
import com.cjy.dao.BlogRepository;
import com.cjy.handler.NotFoundException;
import com.cjy.pojo.Blog;
import com.cjy.pojo.Type;
import com.cjy.pojo.User;
import com.cjy.pojo.vo.BlogQuery;
import com.cjy.service.BlogService;
import com.cjy.util.MarkdownUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import javax.servlet.http.HttpSession;
import java.util.*;

@Service
public class BlogServiceImpl implements BlogService {

    @Autowired
    private BlogRepository blogRepository;

    @Autowired
    private HttpSession session;

    @Value("${fastdfs_domaint}")
    private String fastdfsDomaint;

    @Transactional
    @Override
    public Blog getBlog(Long id) {
        return blogRepository.getOne(id);
    }

    @Transactional
    @Override
    public Blog saveBlog(Blog blog) {
        blog.setCreateTime(new Date());
        blog.setUpdateTime(new Date());
        blog.setViews(0);
        if (blog.getFlag() == null || "".equals(blog.getFlag())){
            blog.setFlag("原创");
        }
        return blogRepository.save(blog);
    }

    @Transactional
    @Override
    public Page<Blog> listBlog(Pageable pageable, BlogQuery blog) {
        final User user = (User) session.getAttribute("user");
        return blogRepository.findAll(new Specification<Blog>() {
            @Override
            public Predicate toPredicate(Root<Blog> root, CriteriaQuery<?> cq, CriteriaBuilder cb) {
                List<Predicate> predicates = new ArrayList<>();
                if (!"".equals(blog.getTitle()) && blog.getTitle() != null){
                    predicates.add(cb.like(root.<String>get("title"),"%"+blog.getTitle()+"%"));
                }
                if (blog.getTypeId() != null){
                    predicates.add(cb.equal(root.<Type>get("type"),blog.getTypeId()));
                }
                if (blog.isRecommend()){
                    predicates.add(cb.equal(root.<Boolean>get("recommend"),blog.isRecommend()));
                }
                if ( !ObjectUtil.isEmpty(user) && user.getRoleId() != 1) {
                    predicates.add(cb.equal(root.<Boolean>get("user").get("id"), user.getId()));
                }
                if (blog.getCheckStatusId() != null) {
                    predicates.add(cb.equal(root.<Type>get("status"),blog.getCheckStatusId()));
                }
                cq.where(predicates.toArray(new Predicate[predicates.size()]));
                return null;
            }
        },pageable);
    }

    @Transactional
    @Override
    public Page<Blog> listBlog(Pageable pageable) {
        return blogRepository.findAllPublished(pageable);
    }

    @Override
    public Page<Blog> listBlogByTypeId(Long id, Pageable pageable) {
        return blogRepository.findAllPublishedAndType(id,pageable);
    }

    @Override
    public Page<Blog> listBlogByTagId(Long id, Pageable pageable) {
        return blogRepository.findAllPublishedAndTags(id,pageable);
    }

    @Transactional
    @Override
    public List<Blog> listBlogTop(Integer size) {
        Sort sort = Sort.by(Sort.Direction.DESC, "updateTime");
        Pageable pageable = PageRequest.of(0,size,sort);
        return blogRepository.findTop(pageable);
    }

    @Override
    public Map<String, List<Blog>> archiveBlog() {
        List<String> years = blogRepository.findGroupYear();
        Map<String , List<Blog>> map = new HashMap<>();
        for (String year:years){
            List<Blog> blogs = blogRepository.findbyYear(year);
            if (blogs != null && blogs.size() != 0) {
                map.put(year,blogs);
            }
        }
        return map;
    }

    @Transactional
    @Override
    public Blog updateBlog(Long id, Blog blog) {
        Blog one = blogRepository.getOne(id);
        if (one == null){
            throw new NotFoundException("该博客不存在");
        }
        blog.setCreateTime(one.getCreateTime());
        blog.setViews(one.getViews());
        BeanUtils.copyProperties(blog,one);
        return blogRepository.save(one);
    }

    @Override
    @Transactional
    public Blog updateBlogAddLike(Long id, Blog blog) {
        Optional<Blog> optionalBlog = blogRepository.findById(id);
        if (optionalBlog.isPresent()) {
            Blog one = optionalBlog.get();
            one.setThumbUpNumber(one.getThumbUpNumber() + 1);
            one.setUpdateTime(new Date());
            one.setId(id);
            return blogRepository.save(one);
        } else {
            throw new NotFoundException("该博客不存在");
        }
    }

    @Override
    @Transactional
    public Blog updateBlogReduceLike(Long id, Blog blog) {
        Optional<Blog> optionalBlog = blogRepository.findById(id);
        if (optionalBlog.isPresent()) {
            Blog one = optionalBlog.get();
            one.setThumbUpNumber(one.getThumbUpNumber() - 1);
            one.setUpdateTime(new Date());
            one.setId(id);
            return blogRepository.save(one);
        } else {
            throw new NotFoundException("该博客不存在");
        }
    }

    @Transactional
    @Override
    public void deleteBlog(Long id) {
        blogRepository.deleteById(id);
    }

    @Transactional
    @Override
    public Page<Blog> listBlogSearch(String query, Pageable pageable) {
        return blogRepository.findAllSearch("%"+query+"%",pageable);
    }

    @Transactional
    @Override
    public Blog getAndConvert(Blog blog) {
        if (blog==null){
            throw new NotFoundException("该博客不存在");
        }
        Blog b = new Blog();
        BeanUtils.copyProperties(blog,b);
        String content = b.getContent();
        b.setContent(MarkdownUtils.markdownToHtmlExtensions(content));
        return b;
    }

    @Override
    public Long countBlog() {
        List<Blog> blogs = blogRepository.countBlog();
        return blogs == null ? 0l : blogs.size();
    }

    @Override
    public int updateBlogViews(Long id) {
        return blogRepository.updateViews(id);
    }

    @Override
    public String passBlog(Long blogId) {
        Blog one = blogRepository.getOne(blogId);
        if (one == null){
            return "博客不存在";
        }
        one.setStatus(1);
        if(blogRepository.save(one) == null) {
            return "审核失败";
        }

        return "ok";
    }

    @Override
    public String rejectBlog(Long blogId, String rejectDes) {
        Blog one = blogRepository.getOne(blogId);
        if (one == null){
            return "博客不存在";
        }
        one.setStatus(-1);
        one.setRejectDes(rejectDes);
        if(blogRepository.save(one) == null) {
            return "审核失败";
        }
        return "ok";
    }

    @Override
    public Integer blogCountByType(Long typeId) {
        List<Blog> byTypeCount = blogRepository.findByTypeCount(typeId);
        return byTypeCount == null ? 0 : byTypeCount.size();
    }

}
